﻿using System;
using System.Collections.Concurrent;
using System.Reflection;

using zijian666.Core;

namespace zijian666.DI
{
    /// <summary>
    /// 可创建委托服务的提供程序
    /// </summary>
    internal static class DelegateServiceHelper
    {

        private static readonly ConcurrentDictionary<(Type, MethodInfo), object?> _delegates = new();
        /// <summary>
        /// 比较2个方法签名是否相同
        /// </summary>
        /// <param name="method1">方法1</param>
        /// <param name="method2">方法2</param>
        /// <returns></returns>
        private static bool CompareMethodSignature(MethodInfo method1, MethodInfo method2)
        {
            if (method1.ReturnType != method2.ReturnType)
            {
                return false;
            }
            var p1 = method1.GetParameters();
            var p2 = method2.GetParameters();
            if (p1.Length != p2.Length)
            {
                return false;
            }
            for (var i = 0; i < p1.Length; i++)
            {
                if (p1[i].ParameterType != p2[i].ParameterType)
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// 转换委托服务
        /// </summary>
        public static T? ConvertDelegate<T>(MethodInfo? method)
            where T: class
        {
            if (method is null)
            {
                return null;
            }
            return (T?)_delegates.GetOrAdd((typeof(T), method), x =>
            {
                var delegateMethod = x.Item1.GetMethod("Invoke");
                if (!CompareMethodSignature(method, x.Item2))
                {
                    return null;
                }
                try
                {
                    return method.CreateDelegate(x.Item1, null);
                }
                catch (Exception ex)
                {
                    ErrorReporter.Report(ex);
                    return null;
                }
            });
        }
    }
}
